CSS2 速查表 - BFC与边距重叠详解

什么是BFC?

在解释 BFC 是什么之前,需要先介绍 BoxFormatting Context的概念。

  • Box: CSS 布局的基本单位

    BoxCSS布局的对象和基本单位, 直观点来说,就是一个页面是由很多个Box组成的。元素的类型和display属性,决定了这个Box的类型。 不同类型的 Box会参与不同的Formatting Context(一个决定如何渲染文档的容器),因此Box内的元素会以不同的方式渲染。让我们看看有哪些盒子:

    什么是BFC?

    在解释 BFC 是什么之前,需要先介绍 BoxFormatting Context的概念。

  • Box: CSS 布局的基本单位

    BoxCSS布局的对象和基本单位, 直观点来说,就是一个页面是由很多个Box组成的。元素的类型和display属性,决定了这个Box的类型。 不同类型的 Box会参与不同的Formatting Context(一个决定如何渲染文档的容器),因此Box内的元素会以不同的方式渲染。让我们看看有哪些盒子:

    block-level boxdisplay 属性为 block, list-item, table 的元素,会生成 block-level box。并且参与 block fomatting context

    inline-level boxdisplay 属性为 inline, inline-block, inline-table 的元素,会生成 inline-level box。并且参与 inline formatting context

    run-in boxcss3 中才有, 这儿先不讲了。

     

  • Formatting context

    Formatting contextW3C CSS2.1 规范中的一个概念。它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。最常见的 Formatting contextBlock fomatting context (简称BFC)Inline formatting context (简称IFC)

    CSS2.1 中只有 BFC 和 IFC
    CSS3 中还增加了 GFC 和 FFC。

     

  • BFC 定义

      BFC(Block formatting context) 直译为 块级格式化上下文。它是一个独立的渲染区域,只有 Block-level box 参与, 它规定了内部的 Block-level Box 如何布局,并且与这个区域外部毫不相干。

  • BFC布局特性

    • 内部的盒会在垂直方向一个接一个排列(可以看作BFC中有一个的常规流);

    • 处于同一个BFC中的元素相互影响,可能会发生margin collapse

    • 每个元素的 margin box 的左边,与容器块 border box 的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此;

    • BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之亦然;

    • 计算 BFC 的高度时,考虑 BFC 所包含的所有元素,连浮动元素也参与计算;

    • 浮动盒区域不叠加到 BFC 上这么多性质有点难以理解,但可以作如下推理来帮助理解:html 的根元素就是 <html>,而根元素会创建一个 BFC,创建一个新的 BFC 时就相当于在这个元素内部创建一个新的,子元素的定位就如同在一个新页面中那样,而这个新旧 html 页面之间时不会相互影响的。上述这个理解并不是最准确的理解,甚至是将因果倒置了(因为 html 是根元素,因此才会有 BFC 的特性,而不是 BFChtml 的特性),但这样的推理可以帮助理解 BFC 这个概念。


哪些元素会生成BFC?

  • 根元素<html>

  • float 属性不为 none

  • positionabsolutefixed

  • displayinline-block, table-cell, table-caption, flex, inline-flex

  • overflow 不为 visible


margin collapse(边距坍塌&边距重叠)

  • 在理解bfc的原理之前先让我们理解一下什么是margin collapse(边距坍塌&边距重叠)
     

     

实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<html>
<style>
.box2{
background: lightblue;
width:100px;
}

</style>

<body>
<div class="box2"></div>
<!--
当box2中没有任何填充内容,文字或图片等。
且没有指定垂直边框 [ boder-top、boder-bottom ]
那么上面的代码在页面上不会显示任何效果。
当我们为box2里填充一些文字:
-->

<div class="box2">
这是box2填充内容
</div>
</body>
</html>


1
2
3
4
5
6
/*或者指定垂直边框 boder-top、boder-bottom*/
.box2{
background: lightblue;
width:100px;
border-top:1px solid transparent ;
}

一个 DIV 和它的子 DIV 特别重视 垂直边框填充,也就好像是,一口锅,里面放个盆,能不能扣住里面的盆,主要看锅盖了,垂直边框或填充就是这个“锅盖”。
于是解决的方式至少有以下三种:
1. 边框,当然可以设置边框为透明;
2. 为父容器添加 padding,或者至少添加 padding-top;
3. 将父容器 BFC 化;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<html>
<style type="text/css">
.box {
background: lightblue;
width: 300px;
height: 250px;
margin: 20px;
/*
1.设置垂直边框
border-top:1px solid transparent ;
border-bottom: 1px solid transparent;

2.为父DIV添加padding,或者至少添加padding-top
padding: 1px 0;

3.各种可BFC化得条件
overflow: hidden;
*/

}

.children {
width: 200px;
background: lightcoral;
height: 200px;
margin: 10px;
}

</style>

<body>
<div class="box"></div>
<div class="box" style="height: auto;">
<div class="children" ></div>
</div>
</body>
</html>

以上三种方式最终效果都一样


代码实例与BFC原理分析

实例 - 1

  • 特性1,特性2,特性4
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    <html>
    <style type="text/css">
    .bfc {
    background-color: lightblue;
    overflow: hidden;
    width: 500px;
    }


    p {
    background-color: lightcoral;
    height: 50px;
    line-height: 50px;
    margin: 10px ;
    }

    .new-bfc{
    overflow: hidden;
    }

    </style>

    <body>
    <div class="bfc">
    <p>children 1</p>
    <p>children 2</p>
    <p>children 3</p>
    <div class="new-bfc">
    <p>children 4</p>
    </div>
    </div>
    </body>
    </html>


实例 - 2

  • 特性3 特性6
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    <html>
    <style type="text/css">
    body {
    margin: 0;
    padding:200px;
    }

    #box {
    background: lightblue;
    width: 600px;
    }

    .right {
    background: lightcoral;
    opacity: 0.5;
    border: 3px solid saddlebrown;
    width: 300px;
    min-height: 100px;
    }

    .left {
    background: lightseagreen;
    border: 3px solid saddlebrown;
    width: 200px;
    height: 200px;
    }

    </style>

    <body>
    <div id="box">
    <div class="left"></div>
    <div class="right"></div>
    </div>
    </body>
    </html>


1
2
3
4
5
6
7
8
/*当给 [ .left ] 加上左浮动*/
.left {
background: lightseagreen;
border: 3px solid saddlebrown;
width: 200px;
height: 200px;
float: left;
}


实例 - 3

  • 特性5
    1
    2
    3
    4
    5
    6
    /* 现在通过 给 [ #box ] 设置 [ overflow:hidden ] 来创建[ BFC ],再看看效果如何。*/             
    #box {
    background: lightblue;
    width: 600px;
    overflow: hidden;
    }


实例 - 4

  • 特性4
    1
    2
    3
    4
    5
    6
    7
    8
    /* 现在通过 给 [ .right ] 中放入一些灰色小块,再看看效果如何。*/      
    .item{
    background: lightslategrey;
    width: 50px;
    height: 50px;
    margin: 10px;
    float: left;
    }


1
2
3
4
5
6
7
8
9
/*接下来,在[ .item ]的父元素 [ .right ] 上我们也添加一个左浮动,再看看效果。 */
.right {
background: lightcoral;
opacity: 0.5;
border: 3px solid saddlebrown;
width: 300px;
min-height: 100px;
float: left;
}


以上就是 BFC 的分析,BFC 的概念比较抽象,但通过实例分析应该能够更好地理解 BFC。在实际中,利用 BFC 可以闭合浮动(实例3),防止与浮动元素重叠(实例4)。同时,由于BFC的隔离作用,可以利用BFC包含一个元素,防止这个元素与BFC外的元素发生margin collapse
参考
http://www.wtoutiao.com/p/AfdISl.html
http://blog.chinaunix.net/uid-22414998-id-3138656.html
http://www.jianshu.com/p/fc1d61dace7b